

#include "picture_filter.h"


int picture_filter(picture_filter_t *fil, AVFrame *inFrame, AVFrame *outFrame)
{
	int ret;

	if (av_buffersrc_add_frame(fil->inFilterCtx, inFrame) < 0) {
		printf( "Error while add frame.\n");
		return -1;
	}

	/* pull filtered pictures from the filtergraph */
	ret = av_buffersink_get_frame(fil->outFilterCtx, outFrame);
	if (ret < 0)
		return -1;
	
	return 0;
}



int picture_filter_init(picture_filter_t *fil, const char *filter_descr, int width, int height, enum AVPixelFormat format)
{
	int ret;
    char args[512];
    AVFilterGraph   *filter_graph;
	AVFilterContext *inFilterCtx;
	AVFilterContext *outFilterCtx;
	AVFilterInOut   *outputs;
	AVFilterInOut   *inputs;
	AVBufferSinkParams *buffersink_params;

	 /* 注册所有过滤器 */
    avfilter_register_all();

	filter_graph = avfilter_graph_alloc();

	/* 过滤器查找 */
    const AVFilter *buffersrc  = avfilter_get_by_name("buffer");
	const AVFilter *buffersink = avfilter_get_by_name("buffersink");
	

    /* buffer video source: the decoded frames from the decoder will be inserted here. */
	snprintf(args, sizeof(args), "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d", 
											width, height,format, 1, 25,1,1);
#if 0
	if (channel_layout)
        len += snprintf(args+len, sizeof(args), ":channel_layout=0x%"PRIx64, channel_layout);
    else
        len += snprintf(args+len, sizeof(args), ":channels=%d", channels);
#endif

	ret = avfilter_graph_create_filter(&inFilterCtx, buffersrc, "in", args, NULL, filter_graph);
	if (ret < 0) {
		printf("Cannot create buffer source\n");
		return ret;
	}

	enum AVPixelFormat pix_fmts[] = { format, AV_PIX_FMT_NONE };
	/* buffer video sink: to terminate the filter chain. */
	buffersink_params = av_buffersink_params_alloc();
	buffersink_params->pixel_fmts = pix_fmts;
	ret = avfilter_graph_create_filter(&outFilterCtx, buffersink, "out", NULL, buffersink_params, filter_graph);
	av_free(buffersink_params);
	if (ret < 0) {
		printf("Cannot create buffer sink\n");
		return ret;
	}

	outputs = avfilter_inout_alloc();
	inputs  = avfilter_inout_alloc();

	/* Endpoints for the filter graph. */
	outputs->name       = av_strdup("in");
	outputs->filter_ctx = inFilterCtx;
	outputs->pad_idx    = 0;
	outputs->next       = NULL;
 
	inputs->name       = av_strdup("out");
	inputs->filter_ctx = outFilterCtx;
	inputs->pad_idx    = 0;
	inputs->next       = NULL;
	
  	// avfilter_graph_parse2
	if ((ret = avfilter_graph_parse_ptr(filter_graph, filter_descr, &inputs, &outputs, NULL)) < 0)
		return ret;

	if ((ret = avfilter_graph_config(filter_graph, NULL)) < 0)
		return ret;

	fil->outputs  = outputs;
	fil->inputs   = inputs;
	fil->filter_graph = filter_graph;
	fil->outFilterCtx = outFilterCtx;
	fil->inFilterCtx  = inFilterCtx;
	return 0;
}


void picture_filter_exit(picture_filter_t *filter)
{
    avfilter_graph_free(&filter->filter_graph);
} 
